package test.circular;

/**
 * FIFO circular queue
 * 
 * @author ginger
 *
 * @param <T>
 */
public class CircularQueue<T> {

	private Object[] queue;
	int head = 0;   // delete from head, -1 to the position to delete
	int tail = 0;   // insert into tail, -1 to the position to add
	private int maxSize;    // only allow capacity - 1, to determine full/empty, when head==tail means empty
	
	public CircularQueue(int capacity) {
		queue = new Object[capacity];
		maxSize = capacity;
	}

	public boolean add(T e) {
		// check full
		int k = (tail + 1) % maxSize;
		if (k == head) {
			System.out.println("The queue is full");
			return false;
		}
		tail = k;
		queue[tail] = e;
		return true;
	}
	
	public T remove() {
		// check empty
		if (head == tail) {
			System.out.println("The queue is empty");
			return null;
		}
		// advance head
		head = (head + 1) % maxSize;
		return (T)queue[head];
	}
	
	public boolean isEmpty() {
		return head == tail;
	}

	public static void main(String[] args) {
		CircularQueue queue = new CircularQueue(4);
		queue.add(1);
		System.out.println("add 1, head=" + queue.head + ", tail=" + queue.tail);
		queue.add(2);
		System.out.println("add 2, head=" + queue.head + ", tail=" + queue.tail);
		queue.add(3);
		System.out.println("add 3, head=" + queue.head + ", tail=" + queue.tail);
		queue.add(4);
		System.out.println("add 4, head=" + queue.head + ", tail=" + queue.tail);
	}
}
